package com.ysh.smartplatform.config;

import com.ysh.smartplatform.security.handlers.MySuccessHandler;
import com.ysh.smartplatform.security.service.MyUserDetailService;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;

/**
 * Created by Jackiechan on 2022/9/15 14:22
 *
 * @author Jackiechan
 * @version 1.0
 * @since 1.0
 */

@EnableWebSecurity //开启权限系统
@Component
//让注解类型的权限生效
@EnableGlobalMethodSecurity(prePostEnabled = true,proxyTargetClass = false,jsr250Enabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private MySuccessHandler mySuccessHandler;

    @Autowired
    public void setMySuccessHandler(MySuccessHandler mySuccessHandler) {
        this.mySuccessHandler = mySuccessHandler;
    }

    //密码的编码器
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    private MyUserDetailService myUserDetailService;

    @Autowired
    public void setMyUserDetailService(MyUserDetailService myUserDetailService) {
        this.myUserDetailService = myUserDetailService;
    }

    @Autowired
    public void setbCryptPasswordEncoder(BCryptPasswordEncoder bCryptPasswordEncoder) {
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
    }

    /**
     * 进行认证配置的,就是告诉我们的spring security我们的密码是什么样的,我们的用户数据在数据库中是怎么查出来的
     * @param auth the {@link AuthenticationManagerBuilder} to use
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserDetailService) //设置如何从数据库中根据用户查询用户数据
                //设置密码的编码器
                .passwordEncoder(bCryptPasswordEncoder);
    }

    /**
     * 这个我们主要配置的不需要经过security的地址,过滤器会直接放行的地址
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/js/**",
                "/css/**",
                "/users/registry",
                "/websocket/*",
                "/humiture/*",
                "/colorcommand/*",
                "/swagger-ui.html",
                "/swagger-ui/*",
                "/swagger-resources/**"
        );
    }

    /**
     * 在这里我们可以配置一些基本信息, 比如可以通过配置的方式来指定我们的地址需要的权限,可以配置登录和退出相关的东西
     * @param http the {@link HttpSecurity} to modify
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.authorizeRequests()
                .and().formLogin()
                .loginProcessingUrl("/login")//登录的处理地址,注意这个地址我们不能自己写,这个地址是security自动生成的
//                .successForwardUrl()//登录成功后跳转到什么地方,我们可以自定义,默认会跳转到首页
                //.failureForwardUrl()//登录失败跳转到什么地方,默认是登录页面
                 .successHandler(mySuccessHandler)//自定义登录成功后做什么业务,我们应该在登录成功之后查询用户角色和权限
                // .failureHandler()//自定义登录失败后做什么业务
                .permitAll()//上面设置的地址不要登录就可以放行
                .and().logout().logoutUrl("/logout")
                .logoutSuccessUrl("/login")//退出成功后跳转到什么地方
                // .logoutSuccessHandler()//自定义退出成功后跳转到什么地方
                .and().authorizeRequests().anyRequest().authenticated();//除了上面的地址外都需要登录才可以访问
    }
}
